package models

import (
	"fmt"
	"gitchina/kly_service/data"
	"gitchina/kly_service/errors"
	"gitchina/kly_service/template"
	"gitchina/kly_service/util"
	"strconv"
	"strings"
	"time"
)

type MakeWaybillRQ struct {
	Id             ID      `json:"waybill_id"`
	StartArea      int     `json:"start_area"`
	StartAddr      string  `json:"start_addr"`
	EndArea        int     `json:"end_area"`
	EndAddr        string  `json:"end_addr"`
	ShipmentTime   string  `json:"shipment_time"`
	CarrierPubId   ID      `json:"carrier_pub_id"`
	CarrierOwnerId int     `json:"-"`
	CargoName      string  `json:"cargo_name"`
	CargoType      int     `json:"cargo_type"`
	CargoBulk      int     `json:"cargo_bulk"`
	CargoWeight    int     `json:"cargo_weight"`
	CargoCount     int     `json:"cargo_count"`
	CargoValue     float32 `json:"cargo_value"`
	ArrivalTime    string  `json:"arrival_time"`
	Deposit        float32 `json:"deposit"`
	Price          float32 `json:"price"`
	Consignor      string  `json:"consignor"`
	Consignee      string  `json:"consignee"`
	ConsigneePhone string  `json:"consignee_phone"`
	Remark         string  `json:"remark"`
	PaymentTerm    int     `json:"payment_term"`
	NeedInvoice    bool    `json:"need_invoice"`
}

type GetWaybillListRQ struct {
	QueryState string `json:"query_state"`
	PageNo     int    `json:"page_no"`
	PageSize   int    `json:"page_size"`
}

type GetWaybillDetailRQ struct {
	Id ID `json:"waybill_id"`
}

type WaybillListRS struct {
	TotalCount int           `json:"total_count"`
	List       []WaybillList `json:"waybill_list"`
}

type WaybillList struct {
	Id           ID      `json:"waybill_id"`
	ShipmentTime string  `json:"shipment_time"`
	StartArea    int     `json:"start_area"`
	EndArea      int     `json:"end_area"`
	Deposit      float32 `json:"deposit"`
	Price        float32 `json:"price"`
	CargoType    int     `json:"cargo_type"`
	CargoName    string  `json:"cargo_name"`
	State        int     `json:"state"`
}

type WaybillDetailRS struct {
	CargoOwner        string      `json:"cargo_owner"`
	CargoOwnerPhone   string      `json:"cargo_owner_phone"`
	CargoOwnerId      ID          `json:"cargo_owner_id"`
	CarrierOwner      string      `json:"carrier_owner"`
	CarrierOwnerPhone string      `json:"carrier_owner_phone"`
	CarrierOwnerId    ID          `json:"carrier_owner_id"`
	StartArea         int         `json:"start_area"`
	StartAddr         string      `json:"start_addr"`
	EndArea           int         `json:"end_area"`
	EndAddr           string      `json:"end_addr"`
	VehicleNo         string      `json:"vehicle_no"`
	VehicleType       int         `json:"vehicle_type"`
	VehcileLen        int         `json:"vehicle_len"`
	VehicleLoad       int         `json:"vehicle_load"`
	ShipmentTime      string      `json:"shipment_time"`
	ArrivalTime       string      `json:"arrival_time"`
	CarrierPubId      ID          `json:"carrier_pub_id"`
	CargoName         string      `json:"cargo_name"`
	CargoType         int         `json:"cargo_type"`
	CargoBulk         int         `json:"cargo_bulk"`
	CargoWeight       int         `json:"cargo_weight"`
	CargoCount        int         `json:"cargo_count"`
	CargoValue        float32     `json:"cargo_value"`
	Deposit           float32     `json:"deposit"`
	Price             float32     `json:"price"`
	Consignor         string      `json:"consignor"`
	Consignee         string      `json:"consignee"`
	ConsigneePhone    string      `json:"consignee_phone"`
	Remark            string      `json:"remark"`
	State             int         `json:"waybill_state"`
	NeedInvoice       bool        `json:"need_invoice"`
	InvoiceInfo       InvoiceInfo `json:"invoice_info"`
}

type UpdateWaybillStateWithParamsRQ struct {
	Id            ID              `json:"waybill_id"`
	UpdateParam   MakeWaybillRQ   `json:"waybill_update_param"`
	NeedInvoice   bool            `json:"need_invoice"`
	NeedInsurance bool            `json:"need_insurance"`
	PaymentTerm   int             `json:"payment_term"`
	InvoiceCorpId int             `json:"invoice_corp_id"`
	InvoiceInfo   InvoicePostAddr `json:"invoice_info"`
	State         WaybillState    `json:"waybill_state"`
}

type Contract struct {
	CargoOwnerName    string
	CargoCorpName     string
	InvoiceCorpName   string
	CargoOwnerPhone   string
	CargoCorpPhone    string
	VehicleNo         string
	CarrierOwnerName  string
	CarrierOwnerPhone string
	CarrierOwnerAddr  string
	DrivingLicneseNo  string
	StartArea         int
	EndArea           int
	CargoName         string
	CargoType         int
	CargoCount        int
	CargoValue        float32
	Price             float32
	Weight            int
	Bulk              int
	Remark            string
	Consignor         string
	Consignee         string
	ConsigneePhone    string
	CargoRcvUnitName  string
	CargoRcvAddr      string
	ArrivalTime       string
	PaymentTerm       int
	IsCorp            bool
}

type WaybillState int

const (
	O_Wait2PayDeposit WaybillState = iota
	O_Wait2Confirm
	O_OnTheWay
	O_OnContract_Wait2Pay
	O_OnContract_Wait2Confirm
	O_OnShipment
	O_OnArrival
	O_Complete
	O_Cancel = 10
)

func (o Order) MakeWaybill(mbrId ID, rq *MakeWaybillRQ) (waybillId ID, err error) {
	var mId, pId, id int64
	var mbrRepo data.MemberRepo
	var orderRepo data.OrderRepo
	if _, _, _, mId, err = mbrId.Decode(); err != nil {
		err = errors.New(errors.MSG_Mbr_Invalid)
		return
	}

	if _, _, _, pId, err = rq.CarrierPubId.Decode(); err != nil {
		err = errors.New(errors.MSG_Logi_Invalid_Pub_Id)
		return
	}

	if !mbrRepo.EnsureCargoOwner(int(mId)) {
		err = errors.New(errors.MSG_Mbr_Only_Cargo_Owner_Can_Make_Waybill)
		return
	}

	if err = o.checkValidWaybillRQ(int(pId), rq); err == nil {
		id, err = orderRepo.MakeWaybill(&data.WaybillDto{
			CargoOwnerId:   int(mId),
			CarrierOwnerId: rq.CarrierOwnerId,
			CarrierPubId:   int(pId),
			ShipmentTime:   rq.ShipmentTime,
			StartArea:      rq.StartArea,
			StartAddr:      rq.StartAddr,
			EndArea:        rq.EndArea,
			EndAddr:        rq.EndAddr,
			CargoName:      rq.CargoName,
			CargoType:      rq.CargoType,
			CargoBulk:      rq.CargoBulk,
			CargoWeight:    rq.CargoWeight,
			CargoCount:     rq.CargoCount,
			CargoValue:     rq.CargoValue,
			ArrivalTime:    rq.ArrivalTime,
			Deposit:        rq.Deposit,
			Price:          rq.Price,
			Consignor:      rq.Consignor,
			Remark:         rq.Remark,
			State:          1,
		})
		if err != nil {
			err = errors.New(errors.MSG_Order_Make_Waybill_Error)
			return
		} else {
			waybillId.Encode(ID_Shard, ID_Ver, ID_Waybill_Category, id)
			if registerId, platform := mbrRepo.GetLoginRegisterId(rq.CarrierOwnerId); len(registerId) > 0 {
				util.Push(fmt.Sprintf(push_format, waybillId), registerId, platform)
			}
		}
	}

	return
}

func (o Order) GetWaybillList(mbrId ID, rq *GetWaybillListRQ) (rs WaybillListRS, err error) {
	var id int64
	var mbrType string
	var rowCount int
	var list []data.GetWaybillListDto
	var mbrRepo data.MemberRepo
	var orderRepo data.OrderRepo

	if _, _, _, id, err = mbrId.Decode(); err != nil {
		err = errors.New(errors.MSG_Mbr_Invalid)
		return
	}
	if mbrType, err = mbrRepo.GetMemberType(int(id)); err != nil {
		util.GetLogger().Error("[model-GetWaybillList] - error:%s", err.Error())
	} else {
		if list, rowCount, err = orderRepo.GetWaybillList(int(id), rq.PageNo, rq.PageSize, rq.QueryState, mbrType); err == nil {
			waybills := make([]WaybillList, len(list))
			for idx, dto := range list {
				var waybillId ID
				waybillId.Encode(ID_Shard, ID_Ver, ID_Waybill_Category, int64(dto.Id))
				waybills[idx] = WaybillList{
					Id:           waybillId,
					ShipmentTime: dto.ShipmentTime,
					StartArea:    dto.StartArea,
					EndArea:      dto.EndArea,
					Price:        dto.Price,
					Deposit:      dto.Deposit,
					CargoType:    dto.CargoType,
					CargoName:    dto.CargoName,
					State:        dto.State,
				}
			}
			rs = WaybillListRS{TotalCount: rowCount, List: waybills}
		} else {
			util.GetLogger().Error("[model-GetWaybillList] - error:%s", err.Error())
			err = nil
		}
	}
	return
}

func (o Order) GetWaybillDetail(waybillId ID) (rs WaybillDetailRS, err error) {
	var id int64
	var repo data.OrderRepo
	var logiRepo data.LogisticsRepo
	var dto data.WaybillDetailDto
	var invoiceInfoDto data.InvoiceInfoDto
	_, _, _, id, err = waybillId.Decode()
	if err != nil {
		err = errors.New(errors.MSG_Order_Invalid_Waybill)
	} else {
		if dto, err = repo.GetWaybillDetail(int(id)); err == nil {
			var carrierPubId, carrierOwnerId, cargoOwnerId ID
			carrierPubId.Encode(ID_Shard, ID_Ver, ID_Carrier_Pub_Category, int64(dto.CarrierPubId))
			carrierOwnerId.Encode(ID_Shard, ID_Ver, ID_Member_Category, int64(dto.CarrierOwnerId))
			cargoOwnerId.Encode(ID_Shard, ID_Ver, ID_Member_Category, int64(dto.CargoOwnerId))
			rs = WaybillDetailRS{
				CargoOwner:        dto.CargoOwner,
				CargoOwnerPhone:   dto.CargoOwnerPhone,
				CargoOwnerId:      cargoOwnerId,
				CarrierOwner:      dto.CarrierOwner,
				CarrierOwnerPhone: dto.CarrierOwnerPhone,
				CarrierOwnerId:    carrierOwnerId,
				StartArea:         dto.StartArea,
				StartAddr:         dto.StartAddr,
				EndArea:           dto.EndArea,
				EndAddr:           dto.EndAddr,
				VehicleNo:         dto.VehicleNo,
				VehicleType:       dto.VehicleType,
				VehcileLen:        dto.VehicleLen,
				VehicleLoad:       dto.VehicleLoad,
				ShipmentTime:      dto.ShipmentTime,
				ArrivalTime:       dto.ArrivalTime,
				CarrierPubId:      carrierPubId,
				CargoName:         dto.CargoName,
				CargoType:         dto.CargoType,
				CargoBulk:         dto.CargoBulk,
				CargoWeight:       dto.CargoWeight,
				CargoCount:        dto.CargoCount,
				CargoValue:        dto.CargoValue,
				Deposit:           dto.Deposit,
				Price:             dto.Price,
				Consignor:         dto.Consignor,
				Consignee:         dto.Consignee,
				ConsigneePhone:    dto.ConsigneePhone,
				Remark:            dto.Remark,
				State:             dto.State,
				NeedInvoice:       dto.NeedInvoice,
			}
			if dto.NeedInvoice {
				if invoiceInfoDto, err = logiRepo.GetInvoiceInfo(int(id)); err == nil {
					rs.InvoiceInfo = InvoiceInfo{
						Title:       invoiceInfoDto.Title,
						Addr:        invoiceInfoDto.Addr,
						RecvName:    invoiceInfoDto.RecvName,
						ZipCode:     invoiceInfoDto.ZipCode,
						RecvPhone:   invoiceInfoDto.RecvPhone,
						TaxNo:       invoiceInfoDto.TaxNo,
						Amount:      invoiceInfoDto.Amount,
						InvoiceCorp: invoiceInfoDto.InvoiceCorp,
					}
				} else {
					util.GetLogger().Error("[model-GetWaybillDetail] - error:%s", err.Error())
					err = nil
				}
			}
		} else {
			util.GetLogger().Error("[model-GetWaybillDetail] - error:%s", err.Error())
			err = nil
		}
	}

	return
}

func (o Order) UpdateWaybill(mbrId ID, rq *MakeWaybillRQ) (err error) {
	var mId, wId, pId int64
	var orderRepo data.OrderRepo
	if _, _, _, mId, err = mbrId.Decode(); err != nil {
		err = errors.New(errors.MSG_Mbr_Invalid)
		return
	}

	if _, _, _, pId, err = rq.CarrierPubId.Decode(); err != nil {
		err = errors.New(errors.MSG_Logi_Invalid_Pub_Id)
		return
	}

	if _, _, _, wId, err = rq.Id.Decode(); err != nil {
		err = errors.New(errors.MSG_Order_Invalid_Waybill_ID)
		return
	}

	if err = o.checkValidWaybillRQ(int(pId), rq); err == nil {
		err = orderRepo.UpdateWaybill(&data.WaybillDto{
			Id:             int(wId),
			CargoOwnerId:   int(mId),
			CarrierOwnerId: rq.CarrierOwnerId,
			CarrierPubId:   int(pId),
			ShipmentTime:   rq.ShipmentTime,
			StartArea:      rq.StartArea,
			StartAddr:      rq.StartAddr,
			EndArea:        rq.EndArea,
			EndAddr:        rq.EndAddr,
			CargoName:      rq.CargoName,
			CargoType:      rq.CargoType,
			CargoBulk:      rq.CargoBulk,
			CargoWeight:    rq.CargoWeight,
			CargoCount:     rq.CargoCount,
			CargoValue:     rq.CargoValue,
			Deposit:        rq.Deposit,
			ArrivalTime:    rq.ArrivalTime,
			Price:          rq.Price,
			Consignor:      rq.Consignor,
			Remark:         rq.Remark,
			Consignee:      rq.Consignee,
			ConsigneePhone: rq.ConsigneePhone,
			State:          1,
		})
		if err != nil {
			err = errors.New(errors.MSG_Order_Update_Waybill_Error)
		}
	}
	return
}

func (o Order) UpdateWaybillState(mbrId ID, rq *UpdateWaybillStateWithParamsRQ) (err error) {
	var mId, wId int64
	var repo data.OrderRepo
	if _, _, _, mId, err = mbrId.Decode(); err != nil {
		err = errors.New(errors.MSG_Mbr_Invalid)
		return
	}

	if _, _, _, wId, err = rq.Id.Decode(); err != nil {
		err = errors.New(errors.MSG_Order_Invalid_Waybill_ID)
		return
	}

	rq.UpdateParam.Id = rq.Id
	//rq.UpdateParam.CarrierOwnerId = int(mId)
	rq.InvoiceCorpId = 1
	if rq.State == O_OnContract_Wait2Confirm {
		updSucc := true
		if rq.UpdateParam.CarrierPubId != "" {
			if err = o.UpdateWaybill(mbrId, &rq.UpdateParam); err != nil {
				util.GetLogger().Error("[model-UpdateWaybillState] - error:%s", err.Error())
			}
			updSucc = err == nil
		}

		if updSucc {
			if rq.NeedInvoice {
				var logisticsRepo data.LogisticsRepo
				if !logisticsRepo.EnsureInvoiceCorpExists(rq.InvoiceCorpId) {
					err = errors.New(errors.MSG_Order_Invalid_Invoice_Corp)
					return
				}
			}

			if err = repo.UpdateWaybillStateWithParams(int(wId), int(mId), rq.InvoiceCorpId, rq.PaymentTerm, rq.NeedInvoice, rq.NeedInsurance, rq.UpdateParam.Price, &data.InvoiceDto{Title: rq.InvoiceInfo.Title, RecvName: rq.InvoiceInfo.RecvName, Addr: rq.InvoiceInfo.Addr, TaxNo: rq.InvoiceInfo.TaxNo, ZipCode: rq.InvoiceInfo.ZipCode, RecvPhone: rq.InvoiceInfo.RecvPhone}); err != nil {
				util.GetLogger().Error("[model-UpdateWaybillState] - error:%s", err.Error())
				err = errors.New(errors.MSG_Order_Upd_Error)
			}
		}
	} else if rq.State == O_Cancel {
		if err = repo.CancelWaybill(int(wId), int(mId)); err != nil {
			util.GetLogger().Error("[model-UpdateWaybillState] - error:%s", err.Error())
			err = errors.New(errors.MSG_Order_Upd_Error)
		}
	} else if rq.State == O_Complete {
		if err = repo.CompleteWaybill(int(wId), int(mId)); err != nil {
			util.GetLogger().Error("[model-UpdateWaybillState] - error:%s", err.Error())
			err = errors.New(errors.MSG_Order_Upd_Error)
		}
	} else {
		if err = repo.UpdateWaybillState(int(wId), int(mId), int(rq.State)); err != nil {
			util.GetLogger().Error("[model-UpdateWaybillState] - error:%s", err.Error())
			err = errors.New(errors.MSG_Order_Upd_Error)
		}
	}

	if err == nil {
		var general General
		var mbrRepo data.MemberRepo
		var ownerDto data.WaybillOwnerDto
		var loginMemberId int
		if ownerDto, err = repo.GetWaybillOwners(int(wId)); err == nil {
			if int(mId) == ownerDto.CargoOwnerId {
				loginMemberId = ownerDto.CarrierOwnerId
			} else {
				loginMemberId = ownerDto.CargoOwnerId
			}

			if registerId, platform := mbrRepo.GetLoginRegisterId(loginMemberId); len(registerId) > 0 {
				util.Push(fmt.Sprintf(push_format, rq.Id), registerId, platform)
			}

			if rq.State == O_OnShipment {
				if len(ownerDto.ConsigneePhone) != 0 {
					util.SendSms(ownerDto.ConsigneePhone, template.GetSignalConsigneeAfterContractTemplate(ownerDto.Consignee, string(rq.Id), ownerDto.StartAddr))
				}
			}
			if rq.State == O_OnArrival {
				if len(ownerDto.ConsigneePhone) != 0 {
					util.SendSms(ownerDto.ConsigneePhone, template.GetSignalConsigneeWhenCargoArrived(string(rq.Id), ownerDto.ArrivalTime, ownerDto.EndAddr))
				}
				if len(ownerDto.Consignor) != 0 {
					if split := strings.Split(ownerDto.Consignor, "|"); len(split) == 2 {
						util.SendSms(split[1], template.GetSignalConsignorWhenCargoArrived(string(rq.Id), ownerDto.ArrivalTime, ownerDto.EndAddr, general.GetPara("phone")))
					}
				}
			}
		}
	}

	return
}

func (o Order) ViewContract(mbrId ID, rq *MakeWaybillRQ) (contract string) {
	var err error
	var mId, wId int64
	var mbrRepo data.MemberRepo
	var orderRepo data.OrderRepo
	if _, _, _, mId, err = mbrId.Decode(); err != nil {
		err = errors.New(errors.MSG_Mbr_Invalid)
		return
	}

	if _, _, _, wId, err = rq.Id.Decode(); err != nil {
		err = errors.New(errors.MSG_Mbr_Invalid)
		return
	}

	if mbrType, err := mbrRepo.GetMemberType(int(mId)); err == nil {
		if mbrType == "1" || mbrType == "3" {
			contract = o.viewTransportContract(int(mId), int(wId), rq, mbrType)
		} else if mbrType == "2" {
			if dto, err := orderRepo.GetWaybillDetail(int(wId)); err == nil {
				if !dto.NeedInvoice {
					contract = o.viewTransportContract(int(mId), int(wId), rq, mbrType)
				} else {
					contract = o.viewPowerOfAttorney(int(mId), int(wId), rq.Id, dto)
				}
			}
		}
	} else {
		util.GetLogger().Error("[model-ViewContract] - error%s", err)
	}
	return
}

func (o Order) viewTransportContract(mId, wId int, rq *MakeWaybillRQ, mbrType string) (contract string) {
	if len(transport_contract) != 0 {
		var orderRepo data.OrderRepo
		var mbrRepo data.MemberRepo
		var logiRepo data.LogisticsRepo
		var tc Contract
		var l Logistics
		var g General
		if detail, err := orderRepo.GetWaybillDetail(wId); err == nil {
			if detail.CarrierOwnerId == mId || detail.CargoOwnerId == mId {
				tc = Contract{
					CargoOwnerName:   detail.CargoOwner,
					CarrierOwnerName: detail.CarrierOwner,
					VehicleNo:        detail.VehicleNo,
					CargoName:        rq.CargoName,
					CargoType:        rq.CargoType,
					CargoValue:       rq.CargoValue,
					Price:            rq.Price,
					Weight:           rq.CargoWeight,
					Bulk:             rq.CargoBulk,
					CargoCount:       rq.CargoCount,
					Remark:           rq.Remark,
					Consignor:        rq.Consignor,
					Consignee:        rq.Consignee,
					ConsigneePhone:   rq.ConsigneePhone,
					CargoRcvUnitName: "#",
					CargoRcvAddr:     rq.EndAddr,
					ArrivalTime:      rq.ArrivalTime,
					PaymentTerm:      rq.PaymentTerm,
					StartArea:        rq.StartArea,
					EndArea:          rq.EndArea,
					CarrierOwnerAddr: "#",
					DrivingLicneseNo: "#",
				}

				if cro, err := mbrRepo.GetCarrierOwner(detail.CarrierOwnerId); err == nil {
					tc.CarrierOwnerName = cro.Name
					tc.CarrierOwnerPhone = cro.Phone
				}

				if mbrType == "1" {
					if cgo, err := mbrRepo.GetCargoOwner(detail.CargoOwnerId); err == nil {
						tc.IsCorp = cgo.IsCorp
						tc.CargoOwnerName = cgo.Name
						tc.CargoCorpName = cgo.CorpName
						tc.CargoOwnerPhone = cgo.Phone
						tc.CargoCorpPhone = cgo.Telpehone
					}
				} else {
					if corp, err := logiRepo.GetLogisticsCorpDetail(detail.CargoOwnerId); err == nil {
						tc.IsCorp = true
						tc.CargoOwnerName = corp.OwnerName
						tc.CargoCorpName = corp.CorpName
						tc.CargoOwnerPhone = corp.OwnerPhone
					}
				}

				if rq.NeedInvoice {
					if invoiceCorp, ok := l.GetInvoiceCorp("1"); ok {
						tc.InvoiceCorpName = invoiceCorp.Name
					}
				}
			}
		}

		var partyAName, partyBName, cargoTypeName, paymentTermName string
		if tc.IsCorp {
			partyAName = tc.CargoCorpName
		} else {
			partyAName = tc.CargoOwnerName
		}

		if rq.NeedInvoice {
			partyBName = tc.InvoiceCorpName
		} else {
			partyBName = tc.CarrierOwnerName
		}

		startArea := l.GetAreaFullName(tc.StartArea)
		endArea := l.GetAreaFullName(tc.EndArea)

		cargoTypeMap := g.GetDict("106")
		if len(cargoTypeMap) > 0 {
			cargoTypeName = cargoTypeMap[strconv.Itoa(tc.CargoType)]
		}
		paymentTermMap := g.GetDict("121")
		if len(paymentTermMap) > 0 {
			paymentTermName = paymentTermMap[strconv.Itoa(tc.PaymentTerm)]
		}

		contract = fmt.Sprintf(transport_contract, rq.Id, partyAName, partyBName, tc.CargoOwnerName,
			tc.CargoOwnerPhone, tc.VehicleNo, tc.CarrierOwnerName, tc.CarrierOwnerPhone, tc.CarrierOwnerAddr,
			tc.DrivingLicneseNo, startArea, endArea, tc.CargoName, cargoTypeName, tc.CargoValue, tc.Price, tc.Weight, tc.Bulk, tc.CargoCount,
			tc.Remark, tc.Consignee, tc.ConsigneePhone, tc.CargoRcvUnitName, tc.CargoRcvAddr, tc.ArrivalTime,
			paymentTermName, partyAName, partyBName, time.Now().Format("2006-01-02 15:04:05"))
	}
	return
}

func (o Order) viewPowerOfAttorney(mId, wId int, waybillId ID, detail data.WaybillDetailDto) (contract string) {
	if len(power_of_attorney) != 0 {
		var mbrRepo data.MemberRepo
		var orderRepo data.OrderRepo
		var tc Contract
		var l Logistics
		var g General

		if detail.CarrierOwnerId == mId || detail.CargoOwnerId == mId {
			tc = Contract{
				CarrierOwnerName: detail.CarrierOwner,
				VehicleNo:        detail.VehicleNo,
				CargoName:        detail.CargoName,
				CargoType:        detail.CargoType,
				CargoCount:       detail.CargoCount,
				CargoValue:       detail.CargoValue,
				Price:            detail.Price,
				Weight:           detail.CargoWeight,
				Bulk:             detail.CargoBulk,
				Remark:           detail.Remark,
				Consignor:        detail.Consignor,
				Consignee:        detail.Consignee,
				ConsigneePhone:   detail.ConsigneePhone,
				CargoRcvUnitName: "#",
				CargoRcvAddr:     detail.EndAddr,
				ArrivalTime:      detail.ArrivalTime,
				PaymentTerm:      detail.PaymentTerm,
				StartArea:        detail.StartArea,
				EndArea:          detail.EndArea,
				CarrierOwnerAddr: "#",
				DrivingLicneseNo: "#",
			}

			if cro, err := mbrRepo.GetCarrierOwner(detail.CarrierOwnerId); err == nil {
				tc.CarrierOwnerName = cro.Name
				tc.CarrierOwnerPhone = cro.Phone
			}

			if invoice, err := orderRepo.GetInvoice(wId); err == nil {
				if invoiceCorp, ok := l.GetInvoiceCorp(strconv.Itoa(invoice.CorpId)); ok {
					tc.InvoiceCorpName = invoiceCorp.Name
				}
			} else {
				util.GetLogger().Error("[model-viewPowerOfAttorney] - error:%s", err.Error())
			}
		}

		var cargoTypeName, paymentTermName string

		startArea := l.GetAreaFullName(tc.StartArea)
		endArea := l.GetAreaFullName(tc.EndArea)

		cargoTypeMap := g.GetDict("106")
		if len(cargoTypeMap) > 0 {
			cargoTypeName = cargoTypeMap[strconv.Itoa(tc.CargoType)]
		}
		paymentTermMap := g.GetDict("121")
		if len(paymentTermMap) > 0 {
			paymentTermName = paymentTermMap[strconv.Itoa(tc.PaymentTerm)]
		}

		contract = fmt.Sprintf(power_of_attorney, waybillId, tc.InvoiceCorpName, tc.CarrierOwnerName,
			tc.VehicleNo, tc.CarrierOwnerPhone, startArea, endArea, tc.CargoName, cargoTypeName, tc.CargoValue,
			tc.Price, tc.Weight, tc.Bulk, tc.CargoCount,
			tc.Remark, tc.Consignee, tc.ConsigneePhone, tc.CargoRcvUnitName, tc.CargoRcvAddr, tc.ArrivalTime,
			paymentTermName, tc.InvoiceCorpName, tc.CarrierOwnerName, time.Now().Format("2006-01-02 15:04:05"))
	}
	return
}

func (o Order) ViewLetterOfAuthorization(mbrId, waybillId ID) (contract string) {
	if len(letter_of_authorization) != 0 {
		var mId, wId int64
		var err error
		var repo data.OrderRepo
		if _, _, _, mId, err = mbrId.Decode(); err != nil {
			err = errors.New(errors.MSG_Mbr_Invalid)
			return
		}

		if _, _, _, wId, err = waybillId.Decode(); err != nil {
			err = errors.New(errors.MSG_Mbr_Invalid)
			return
		}

		if dto, err := repo.GetLetterOfAuthorization(int(mId), int(wId)); err == nil {
			contract = fmt.Sprintf(letter_of_authorization, fmt.Sprintf("IP%s", string(waybillId)), "赵乙林",
				dto.IDCardNo, waybillId, dto.CarrierOwner, dto.IDCardNo, dto.VehicleNo, time.Now().Format("2006-01-02"))
		}
	}
	return
}

func (o Order) checkValidWaybillRQ(pubId int, rq *MakeWaybillRQ) (err error) {
	var shipmentTime, arrivalTime time.Time
	var pub data.CarrierPubDetail
	var logiRepo data.LogisticsRepo
	//var orderRepo data.OrderRepo
	//check cargo type

	// if rq.StartArea%10000 == 0 || rq.EndArea%10000 == 0 {
	// 	err = errors.New(errors.MSG_Order_Invalid_Start_Or_End_Area)
	// 	return
	// }

	if len(rq.CargoName) == 0 {
		err = errors.New(errors.MSG_Order_Invalid_Cargo_Name)
		return
	}

	if pub, err = logiRepo.GetCarrierPubDetail(pubId); err == nil {
		rq.CarrierOwnerId = pub.MemberId
		// if pub.SrcCity == 0 {
		// 	if pub.SrcProvince != rq.StartArea-rq.StartArea%10000 {
		// 		err = errors.New(errors.MSG_Order_Invalid_Start_Area)
		// 		return
		// 	}
		// } else {
		// 	if pub.SrcCity != rq.StartArea {
		// 		err = errors.New(errors.MSG_Order_Invalid_Start_Area)
		// 		return
		// 	}
		// }

		// if pub.DestCity == 0 {
		// 	if pub.DestProvince != rq.EndArea-rq.EndArea%10000 {
		// 		err = errors.New(errors.MSG_Order_Invalid_End_Area)
		// 		return
		// 	}
		// } else {
		// 	if pub.DestCity != rq.EndArea {
		// 		err = errors.New(errors.MSG_Order_Invalid_End_Area)
		// 		return
		// 	}
		// }

		if len(rq.ShipmentTime) == 10 {
			if shipmentTime, err = time.Parse("2006-01-02", rq.ShipmentTime); err != nil {
				err = errors.New(errors.MSG_Order_Invalid_Shipment_Time)
				return
			}
		} else if len(rq.ShipmentTime) == 19 {
			if shipmentTime, err = time.Parse("2006-01-02 15:04:05", rq.ShipmentTime); err != nil {
				err = errors.New(errors.MSG_Order_Invalid_Shipment_Time)
				return
			} else {
				rq.ShipmentTime = shipmentTime.Format("2006-01-02 00:00:00")
			}
		} else {
			err = errors.New(errors.MSG_Order_Invalid_Shipment_Time)
		}

		if len(rq.ArrivalTime) != 0 {
			if len(rq.ArrivalTime) == 10 {
				if arrivalTime, err = time.Parse("2006-01-02", rq.ArrivalTime); err != nil {
					err = errors.New(errors.MSG_Order_Invalid_Arrival_Time)
					return
				}
			} else if len(rq.ArrivalTime) == 19 {
				if arrivalTime, err = time.Parse("2006-01-02 15:04:05", rq.ArrivalTime); err != nil {
					err = errors.New(errors.MSG_Order_Invalid_Arrival_Time)
					return
				} else {
					rq.ArrivalTime = arrivalTime.Format("2006-01-02 00:00:00")
				}
			} else {
				err = errors.New(errors.MSG_Order_Invalid_Arrival_Time)
			}
		}
	} else {
		err = errors.New(errors.MSG_Order_Invalid_Carrier_Pub)
	}
	return err
}
